package com.umeox.watch.arithmetictest;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.umeox.moto.watch.themes.BuildConfig;
import com.umeox.moto.watch.themes.app.ThemeAppCompatActivity;
import com.umeox.watch.arithmetictest.io.ThreadExecutor;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 算数游戏定义：
 * <p>
 * 1.难度定义
 * A+B=C ，A、B、C都取非负的整数，所有题目内容不固定，A、B随机取值，满足相应难度的条件即可。
 * 简单：10以内的加减法,0≤A<10 ， 0≤B<10，
 * 中等：20以内的加减法，0≤A<20 ， 0≤B<20
 * 困难：20以内的加减乘除法，0≤A<20 ， 0≤B<20，
 * 注：除法时，B≠0，且能整除；
 * 减法时，A≥B。
 * <p>
 * 2.计分规则：10道题，每题10分，不累计，不保存，中途返回也清除数据
 * <p>
 * 3.答错提示：答错弹出提示框再进入下一题，答对直接跳下一题
 */
public class ArithmeticTestActivity extends ThemeAppCompatActivity implements View.OnClickListener {
    private static final String TAG = "ArithmeticTestActivity";

    private List<String> topics;
    private List<Boolean> results;
    private int index;
    private int topicCount;
    private int totalScore;
    private int perScore;

    private TextView tvNum, tvTopic, tvScore;
    private ImageView ivIncorrect, ivWrong, ivRight;
    private RelativeLayout rlResult;
    private Handler mHandler;
    private ThreadPoolExecutor mPoolExecutor;
    private AtomicBoolean clickable = new AtomicBoolean(false);
    private int mLevel;
    public static final String FORMAT = "%d%s%d=%d";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_arithmetic_test);
        mHandler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                if (msg.what == 0) {
                    setTopic();
                    return true;
                }
                return false;
            }
        });
        initView();
        initData();
    }


    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        initData();
    }

    private void initView() {
        tvNum = findViewById(R.id.tvNum);
        tvTopic = findViewById(R.id.tvTopic);

        tvScore = findViewById(R.id.tvScore);

        ivIncorrect = findViewById(R.id.ivIncorrect);
        rlResult = findViewById(R.id.rlResult);

        ivIncorrect.setVisibility(View.GONE);
        rlResult.setVisibility(View.GONE);

        ivWrong = findViewById(R.id.ivWrong);
        ivRight = findViewById(R.id.ivRight);

        ivWrong.setOnClickListener(this);
        ivRight.setOnClickListener(this);

        ivWrong.setClickable(false);
        ivRight.setClickable(false);

        findViewById(R.id.ivBack).setOnClickListener(this);
    }

    /**
     * 简单：10以内的加减法,0≤A<10 ， 0≤B<10，
     * 中等：20以内的加减法，0≤A<20 ， 0≤B<20
     * 困难：20以内的加减乘除法，0≤A<20 ， 0≤B<20
     * 注：除法时，B≠0，且能整除；
     * 减法时，A≥B。
     */
    private void initData() {
        mLevel = getIntent().getIntExtra("level", 1);
        topics = new ArrayList<>();
        results = new ArrayList<>();

        clickable.set(false);
        totalScore = 100;
        topicCount = 10;
        perScore = totalScore / topicCount;
        index = 0;

        mPoolExecutor = ThreadExecutor.getInstance().io();
        mPoolExecutor.execute(mTopicTask);

    }

    final Runnable mTopicTask = new Runnable() {
        @Override
        public void run() {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "开始出题 " + mLevel + " thread " + Thread.currentThread().getName());
            }
            if (mLevel == 1) {
                generateAdditionAndSubtractionTopic(10, topicCount);
            } else if (mLevel == 2) {
                generateAdditionAndSubtractionTopic(20, topicCount);
            } else {
                for (int i = 0; i < topicCount; i++) {
                    //随机生成加减法和乘除法题目
                    switch (Operation.random()) {
                        case MULTIPLY:
                            generateMultiplyTopic(20);
                            break;
                        case DIVIDE:
                            generateDivideTopic(20);
                            break;
                        default:
                            generateAdditionAndSubtractionTopic(20, 1);
                            break;
                    }
                }
            }
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "出题完成");
            }
            if (mHandler != null) {
                mHandler.sendEmptyMessage(0);
            }
        }
    };

    private void setTopic() {
        if (index > topics.size() - 1) {
            return;
        }
        if (clickable.compareAndSet(false, true)) {
            tvNum.setText(String.format(Locale.getDefault(), "%d/%d", index + 1, topicCount));
            tvTopic.setText(topics.get(index));
            ivWrong.setClickable(true);
            ivRight.setClickable(true);
        } else {
            Log.d(TAG, "setTopic>>>clickable true");
        }
    }

    /**
     * 递归生成加减法题目
     */
    private void generateAdditionAndSubtractionTopic(int range, int size) {
        String topic;
        int a, b, c;
        boolean r;
        Operation operation;

        Random ra = new Random();
        int count = 0;
        do {

            try {
                //两个小于10的整数加减法，结果最大不会超过18，随机一个18以内的整数，根据随机数大小来决定加减法
                //两个小于20的整数加减法，结果最大不会超过38，随机一个38以内的整数，根据随机数大小来决定加减法
                c = ra.nextInt(range * 2 - 2);
                //该题是正确的还是错误的结果
                r = ra.nextBoolean();

                if (c > (range - 1)) {
                    //大于(range - 1)肯定只能是加法
                    operation = Operation.PLUS;
                    a = ra.nextInt(range);
                    b = c - a;

                    if (!r) {
                        b = randomInt(0, range, b);
                    }

                    topic = String.format(Locale.getDefault(), FORMAT, a, operation.symbol, b, c);
                } else {

                    operation = Operation.MINUS;
                    a = ra.nextInt(range - c) + c;
                    b = a - c;
                    if (!r) {
                        //b<a
                        if (a == 0 || a == 1 && b == 0) {
                            a = ra.nextInt(5) + 1;
                            c = 0;
                        } else {
                            b = randomInt(0, a, b);
                        }

                    }

                    topic = String.format(Locale.getDefault(), FORMAT, a, operation.symbol, b, c);
                }
            } catch (Exception e) {
                Log.e(TAG, "generateAdditionAndSubtractionTopic", e);
                topic = null;
                r = false;
            }

            if (!TextUtils.isEmpty(topic) && !topics.contains(topic)) {
                topics.add(topic);
                results.add(r);
                count++;
            } else {
                if (BuildConfig.DEBUG) {
                    Log.d(TAG, "题目[" + topic + "]已存在，当前已成" + count + "还剩" + (size - count));
                }
            }
        } while (count < size);
    }

    /**
     * 生成乘法题目
     */
    private void generateMultiplyTopic(int range) {
        String topic;
        int a, b, c;
        boolean r;
        Operation operation = Operation.MULTIPLY;
        Random ra = new Random();
        for (; ; ) {
            try {
                a = ra.nextInt(range);
                b = ra.nextInt(range);
                c = a * b;
                r = ra.nextBoolean();
                if (!r) {
                    //随机产生错误的结果d = c - a * n(n<a)或者是d = c - b * n(n<b);
                    int n;
                    if (a == 0 || b == 0) {
                        c = 1;
                    } else if (a < 10 || a < b) {
                        n = randomInt(1, a);
                        c = c - a * n;
                    } else if (b < 10 || b < a) {
                        n = randomInt(1, b);
                        c = c - b * n;
                    } else {
                        c = c - a - b;
                    }
                }
                topic = String.format(Locale.getDefault(), FORMAT, a, operation.symbol, b, c);
            } catch (Exception e) {
                e.printStackTrace();
                topic = null;
                r = false;
            }
            if (!topics.contains(topic)) {
                topics.add(topic);
                results.add(r);
                break;
            }
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "乘法题目[" + topic + "]已存在");
            }
        }
    }

    /**
     * 生成除法题目，只能整除
     */
    private void generateDivideTopic(int range) {
        String topic;
        int a, b, c;
        boolean r;
        Operation operation = Operation.DIVIDE;

        for (; ; ) {
            try {
                c = randomInt(0, range + 1);
                if (c == 0) {
                    a = 0;
                    b = randomInt(1, range + 1);
                } else {
                    //只能整除，a >= b
                    List<Integer> tempA = new ArrayList<>();
                    for (int i = 1; i < range + 1; i++) {
                        //range范围内能被c整除的数
                        if (i % c == 0) {
                            tempA.add(i);
                        }
                    }
                    int randomIndex = randomInt(0, tempA.size());
                    a = tempA.get(randomIndex);
                    b = a / c;
                }

                Random ra = new Random();
                r = ra.nextBoolean();
                if (!r) {
                    //随机产生错误的结果d = c - n(n<c)或者是d = c + n(n<c)
                    if (c == 0) {
                        c = 1;
                    } else {
                        if (ra.nextBoolean()) {
                            c = c + randomInt(0, c);
                        } else {
                            c = c - randomInt(0, c);
                        }
                    }
                }
                topic = String.format(Locale.getDefault(), FORMAT, a, operation.symbol, b, c);
            } catch (Exception e) {
                e.printStackTrace();
                topic = null;
                r = false;
            }

            if (!TextUtils.isEmpty(topic) && !topics.contains(topic)) {
                topics.add(topic);
                results.add(r);
                break;
            }
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "除法题目[" + topic + "]已存在");
            }
        }
    }

    /**
     * 随机生成一个整数大于等于min，小于max
     * 结果不包含在exclude中的数字
     */
    private int randomInt(int min, int max, int... excludes) {


        if (min == max) {
            return min;
        }
        int result;
        Random ra = new Random();
        for (; ; ) {

            result = ra.nextInt(max - min) + min;
            if (excludes == null
                    || excludes.length == 0) {
                return result;
            }
            boolean returnFlag = true;
            for (int exclude : excludes) {
                if (exclude == result) {
                    returnFlag = false;
                    break;
                }
            }
            if (returnFlag) {
                return result;
            }
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.ivBack:
                finish();
                break;
            case R.id.ivWrong:
                answer(false);
                break;
            case R.id.ivRight:
                answer(true);
                break;
            default:
                break;
        }
    }

    private void answer(boolean right) {
        if (clickable.compareAndSet(true, false)) {
            ivWrong.setClickable(false);
            ivRight.setClickable(false);

            if (results.get(index) == right) {
                next();
            } else {
                totalScore -= perScore;
                ivIncorrect.setVisibility(View.VISIBLE);
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        ivIncorrect.setVisibility(View.GONE);
                        next();
                    }
                }, 1500);
            }
        } else {
            Log.d(TAG, "answer>>>clickable false");
        }
    }

    private void next() {
        if (index++ < topicCount - 1) {
            setTopic();
        } else {
            rlResult.setVisibility(View.VISIBLE);
            tvScore.setText(String.valueOf(totalScore));
        }
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        mHandler.removeCallbacksAndMessages(null);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mPoolExecutor != null) {
            Log.i(TAG, "onDestroy: ");
            mPoolExecutor.remove(mTopicTask);

        }
        mHandler = null;
    }

    private enum Operation {
        /**
         * 加减乘除
         */
        PLUS("+"), MINUS("-"), MULTIPLY("×"), DIVIDE("÷");
        String symbol;

        Operation(String method) {
            symbol = method;
        }

        public static Operation random() {
            Random ra = new Random();
            switch (ra.nextInt(4)) {
                case 0:
                    return Operation.PLUS;
                case 1:
                    return Operation.MINUS;
                case 2:
                    return Operation.MULTIPLY;
                default:
                    return Operation.DIVIDE;
            }
        }
    }
}
